You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
45 lines
1.7 KiB
45 lines
1.7 KiB
import { dbGlobal } from "drizzle-pkg/lib/db";
|
|
import { sessions, users } from "drizzle-pkg/lib/schema/auth";
|
|
import { eq } from "drizzle-orm";
|
|
import { requireAdmin } from "#server/utils/admin-guard";
|
|
import { assertUnderRateLimit } from "#server/utils/simple-rate-limit";
|
|
import { getRequestIP } from "h3";
|
|
|
|
type Body = {
|
|
status: "active" | "disabled";
|
|
};
|
|
|
|
export default defineWrappedResponseHandler(async (event) => {
|
|
await requireAdmin(event);
|
|
const ip = getRequestIP(event, { xForwardedFor: true }) ?? "unknown";
|
|
assertUnderRateLimit(`admin-users-patch:${ip}`, 60, 60_000);
|
|
|
|
const id = Number(event.context.params?.id);
|
|
if (!Number.isInteger(id) || id < 1) {
|
|
throw createError({ statusCode: 400, statusMessage: "无效的用户 id" });
|
|
}
|
|
|
|
const body = await readBody<Body>(event);
|
|
if (body.status !== "active" && body.status !== "disabled") {
|
|
throw createError({ statusCode: 400, statusMessage: "status 须为 active 或 disabled" });
|
|
}
|
|
|
|
const [target] = await dbGlobal.select({ role: users.role }).from(users).where(eq(users.id, id)).limit(1);
|
|
if (!target) {
|
|
throw createError({ statusCode: 404, statusMessage: "用户不存在" });
|
|
}
|
|
if (target.role === "admin" && body.status === "disabled") {
|
|
const admins = await dbGlobal.select({ id: users.id }).from(users).where(eq(users.role, "admin"));
|
|
if (admins.length <= 1) {
|
|
throw createError({ statusCode: 400, statusMessage: "不能禁用唯一的管理员" });
|
|
}
|
|
}
|
|
|
|
await dbGlobal.update(users).set({ status: body.status }).where(eq(users.id, id));
|
|
|
|
if (body.status === "disabled") {
|
|
await dbGlobal.delete(sessions).where(eq(sessions.userId, id));
|
|
}
|
|
|
|
return R.success({ ok: true });
|
|
});
|
|
|